package savelog;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.List;

import android.app.ProgressDialog;
import android.content.Context;
import android.os.AsyncTask;
import android.widget.Toast;

import com.dropbox.client2.DropboxAPI;
import com.dropbox.client2.DropboxAPI.UploadRequest;
import com.dropbox.client2.ProgressListener;
import com.dropbox.client2.exception.DropboxException;
import com.dropbox.client2.exception.DropboxFileSizeException;
import com.dropbox.client2.exception.DropboxIOException;
import com.dropbox.client2.exception.DropboxParseException;
import com.dropbox.client2.exception.DropboxPartialFileException;
import com.dropbox.client2.exception.DropboxServerException;
import com.dropbox.client2.exception.DropboxUnlinkedException;

/**
 * Title: Upload class for CSIS 343 Final Project 
 * Description: CS 343 Final Project - Upload This class will handle uploading all save files to dropbox
 * 
 * @author Erik Olson
 * @email erik.olson-5@my.uwrf.edu
 * @author Mike Harmon
 * @email michael.harmon@my.uwrf.edu
 * @author Jack Friermuth
 * @email jack.friermuth@my.uwrf.edu
 * @author Luke Vang
 * @email luke.vang@my.uwrf.edu
 * @author Casey Golla
 * @email casey.golla@my.uwrf.edu
 * @date December 4th 2012
 */
public class Upload extends AsyncTask<List<Saves>, Long, Boolean> {

	private DropboxAPI<?> mApi;
	private String mPath;
	private File mFile;

	private long mFileLen;
	private UploadRequest mRequest;
	private Context mContext;
	private final ProgressDialog mDialog;

	private String mErrorMsg;

	/**
	 * Alternate constructor for Upload
	 * @param Context context	  :		Current state of the app
	 * @param DropboxAPI api	  :		Helper class for dropbox api functions
	 * @param String dropboxPath :		Path to your device folder in dropbox
	 */
	public Upload(Context context, DropboxAPI<?> api, String dropboxPath) {

		//setting provided variables
		mContext = context.getApplicationContext();
		mApi = api;
		mPath = dropboxPath;

		//setting up a dialog to show progress of upload
		mDialog = new ProgressDialog(context);
		mDialog.setMax(100);
		mDialog.setMessage("Uploading provided files");
		mDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
		mDialog.setProgress(0);
		mDialog.show();
	}

	/**
	 * Method to perform the upload on an async thread in the background
	 * @Override
	 */
	protected Boolean doInBackground(List<Saves>... saves) {
		try {
			//getting save files
			List<Saves> loopList = saves[0];
			
			//looping through provided save files and uploading them
			for (int i = 0; i < loopList.size(); i++) {
				// By creating a request, we get a handle to the putFile
				// operation,
				// so we can cancel it later if we want to
				
				//getting save file we want to push
				mFile = new File(loopList.get(i).getSave_src());
				FileInputStream fis = new FileInputStream(mFile);
				String path = mPath + mFile.getName();
				
				//pushing file to dropbox
				mRequest = mApi.putFileOverwriteRequest(path, fis,
						mFile.length(), new ProgressListener() {
							@Override
							public long progressInterval() {
								// Update the progress bar every half-second or
								// so
								return 500;
							}

							@Override
							public void onProgress(long bytes, long total) {
								publishProgress(bytes);
							}
						});

				if (mRequest != null) {
					mRequest.upload();
					
					//once all files are uploaded return
					if (i == (loopList.size() - 1)){
						return true;
					}
				}
			}
		} catch (DropboxUnlinkedException e) {
			// This session wasn't authenticated properly or user unlinked
			mErrorMsg = "This app wasn't authenticated properly.";
		} catch (DropboxFileSizeException e) {
			// File size too big to upload via the API
			mErrorMsg = "This file is too big to upload";
		} catch (DropboxPartialFileException e) {
			// We canceled the operation
			mErrorMsg = "Upload canceled";
		} catch (DropboxServerException e) {
			// Server-side exception. These are examples of what could happen,
			// but we don't do anything special with them here.
			if (e.error == DropboxServerException._401_UNAUTHORIZED) {
				// Unauthorized, so we should unlink them. You may want to
				// automatically log the user out in this case.
			} else if (e.error == DropboxServerException._403_FORBIDDEN) {
				// Not allowed to access this
			} else if (e.error == DropboxServerException._404_NOT_FOUND) {
				// path not found (or if it was the thumbnail, can't be
				// thumbnailed)
			} else if (e.error == DropboxServerException._507_INSUFFICIENT_STORAGE) {
				// user is over quota
			} else {
				// Something else
			}
			// This gets the Dropbox error, translated into the user's language
			mErrorMsg = e.body.userError;
			if (mErrorMsg == null) {
				mErrorMsg = e.body.error;
			}
		} catch (DropboxIOException e) {
			// Happens all the time, probably want to retry automatically.
			mErrorMsg = "Network error.  Try again.";
		} catch (DropboxParseException e) {
			// Probably due to Dropbox server restarting, should retry
			mErrorMsg = "Dropbox error.  Try again.";
		} catch (DropboxException e) {
			// Unknown error
			mErrorMsg = "Unknown error.  Try again.";
		} catch (FileNotFoundException e) {
		}
		return false;
	}

	/**
	 * Method to update the progress bar
	 * @Override
	 */
	protected void onProgressUpdate(Long... progress) {
		int percent = (int) (100.0 * (double) progress[0] / mFileLen + 0.5);
		mDialog.setProgress(percent);
	}

	/**
	 * Method to display a success or error message once the upload is done
	 * @Override
	 */
	protected void onPostExecute(Boolean result) {
		mDialog.dismiss();
		if (result) {
			showToast("Save successfully uploaded");
		} else {
			showToast(mErrorMsg);
		}
	}

	/**
	 * Method to display a toast
	 * @param String msg :		message to be displayed
	 */
	private void showToast(String msg) {
		Toast error = Toast.makeText(mContext, msg, Toast.LENGTH_LONG);
		error.show();
	}

}
